package wiki.xsx.core.jmeter.core.postprocessor;

import wiki.xsx.core.jmeter.core.enums.JmeterScope;
import wiki.xsx.core.jmeter.core.util.JmeterOptional;
import wiki.xsx.core.jmeter.core.util.JmeterScopeUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor;
import org.apache.jmeter.extractor.json.jsonpath.gui.JSONPostProcessorGui;
import org.apache.jmeter.processor.PostProcessor;
import org.apache.jmeter.testelement.TestElement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 默认json后置处理器
 *
 * @author xsx
 * @date 2022/8/31
 * @since 1.8
 * <p>
 * Copyright (c) 2022 xsx All Rights Reserved.
 * easy-jmeter is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 * http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * </p>
 */
@Data
@Accessors(chain = true)
public class JmeterDefaultJsonPostProcessor implements JmeterPostProcessor {

    /**
     * 测试类名称
     */
    public static final String TEST_CLASS_NAME = JSONPostProcessor.class.getName();
    /**
     * GUI类名称
     */
    public static final String GUI_CLASS_NAME = JSONPostProcessorGui.class.getName();

    /**
     * 处理器名称
     */
    private String name;
    /**
     * 处理器注释
     */
    private String comment;
    /**
     * 范围变量名称（自定义变量）
     */
    private String scopeVariableName;
    /**
     * json变量列表
     */
    private List<JmeterJsonVariable> jsonVariables;
    /**
     * 处理器范围
     */
    private JmeterScope scope;
    /**
     * 是否添加拼接变量
     * <p>后缀：“_ALL”，分隔符：“,”</p>
     */
    private Boolean isAddJoinVariable;

    /**
     * 无参构造
     */
    private JmeterDefaultJsonPostProcessor() {
    }

    /**
     * 获取json后置处理器实例
     *
     * @return 返回json后置处理器实例
     */
    public static JmeterDefaultJsonPostProcessor getInstance() {
        return new JmeterDefaultJsonPostProcessor();
    }

    /**
     * 初始化json变量容量
     *
     * @param initialCapacity 初始容量
     * @return 返回json后置处理器
     */
    public JmeterDefaultJsonPostProcessor initialJsonVariableCapacity(int initialCapacity) {
        this.jsonVariables = new ArrayList<>(initialCapacity);
        return this;
    }

    /**
     * 添加json变量
     *
     * @param jsonVariables json变量
     * @return 返回json后置处理器
     */
    public JmeterDefaultJsonPostProcessor addJsonVariable(JmeterJsonVariable... jsonVariables) {
        // 如果json变量为空，则初始化json变量
        if (this.jsonVariables == null) {
            // 初始化json变量
            this.jsonVariables = new ArrayList<>(10);
        }
        // 添加json变量
        Collections.addAll(this.jsonVariables, jsonVariables);
        // 返回json后置处理器
        return this;
    }

    /**
     * 创建后置处理器
     *
     * @return 返回后置处理器
     */
    @Override
    public PostProcessor create() {
        // 创建json后置处理器
        JSONPostProcessor jsonPostProcessor = new JSONPostProcessor();
        // 设置测试类名称
        jsonPostProcessor.setProperty(TestElement.TEST_CLASS, TEST_CLASS_NAME);
        // 设置GUI类名称
        jsonPostProcessor.setProperty(TestElement.GUI_CLASS, GUI_CLASS_NAME);
        // 设置启用
        jsonPostProcessor.setEnabled(true);
        // 设置处理器名称
        jsonPostProcessor.setName(JmeterOptional.ofNullable(this.name).orElse("json提取器"));
        // 设置处理器注释
        jsonPostProcessor.setComment(JmeterOptional.ofNullable(this.comment).orElse(""));
        // 设置是否添加拼接变量
        jsonPostProcessor.setComputeConcatenation(JmeterOptional.ofNullable(this.isAddJoinVariable).orElse(Boolean.FALSE));
        // 设置范围
        JmeterOptional.ofNullable(this.scope).orElse(JmeterOptional.of(JmeterScope.ONLY_MAIN_SAMPLE)).ifPresent(scope -> JmeterScopeUtil.initScope(scope, this.scopeVariableName, jsonPostProcessor));
        // 设置json变量
        JmeterOptional.ofNullable(this.jsonVariables).ifPresent(v -> this.initJsonVariables(v, jsonPostProcessor));
        // 返回json后置处理器
        return jsonPostProcessor;
    }

    /**
     * 初始化json变量
     *
     * @param jsonVariables     json变量列表
     * @param jsonPostProcessor json后置处理器
     */
    private void initJsonVariables(List<JmeterJsonVariable> jsonVariables, JSONPostProcessor jsonPostProcessor) {
        // 创建变量名称构建器
        StringBuilder variableNames = new StringBuilder();
        // 创建json路径构建器
        StringBuilder jsonPaths = new StringBuilder();
        // 创建匹配编号构建器
        StringBuilder matchNoes = new StringBuilder();
        // 创建默认值构建器
        StringBuilder defaultValues = new StringBuilder();
        // 遍历变量列表
        jsonVariables.forEach(
                variable -> {
                    // 拼接变量名称
                    JmeterOptional.ofNullable(variable.getVariableName()).ifPresent(v -> variableNames.append(v).append(';'));
                    // 拼接json路径
                    JmeterOptional.ofNullable(variable.getJsonPath()).ifPresent(v -> jsonPaths.append(v).append(';'));
                    // 拼接匹配编号
                    JmeterOptional.ofNullable(variable.getMatchNo()).ifPresent(v -> matchNoes.append(v).append(';'));
                    // 拼接默认值
                    JmeterOptional.ofNullable(variable.getDefaultValue()).ifPresent(v -> defaultValues.append(v).append(';'));
                }
        );
        // 设置变量名称
        jsonPostProcessor.setRefNames(variableNames.toString());
        // 设置json路径
        jsonPostProcessor.setJsonPathExpressions(jsonPaths.toString());
        // 设置匹配编号
        jsonPostProcessor.setMatchNumbers(matchNoes.toString());
        // 设置默认值
        jsonPostProcessor.setDefaultValues(defaultValues.toString());
    }
}
